package com.brillilab.service.core.plans.impl;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.brillilab.common.utils.DateUtil;
import com.brillilab.dao.mapper.plans.PlanTargetGroupMapper;
import com.brillilab.domain.enums.common.BoolEnum;
import com.brillilab.domain.enums.experiment.ExperimentStateEnum;
import com.brillilab.domain.enums.topic.TopicStateEnum;
import com.brillilab.domain.po.experiments.Experiment;
import com.brillilab.domain.po.plans.Plan;
import com.brillilab.domain.po.plans.PlanExperimentGroup;
import com.brillilab.domain.po.plans.PlanTargetGroup;
import com.brillilab.domain.po.topics.TopicExperiment;
import com.brillilab.domain.po.topics.TopicTarget;
import com.brillilab.domain.vo.topics.TopicTargetPlanDateVo;
import com.brillilab.service.core.experiments.IExperimentService;
import com.brillilab.service.core.plans.IPlanExperimentGroupService;
import com.brillilab.service.core.plans.IPlanService;
import com.brillilab.service.core.plans.IPlanTargetGroupService;

/**
 * <p>
 * 计划实验流组表 服务实现类
 * </p>
 *
 * @author zlb
 * @since 2019-09-05
 */
@Service
@Transactional
public class PlanTargetGroupServiceImpl implements IPlanTargetGroupService {

	@Resource
	private PlanTargetGroupMapper planTargetGroupMapper;
	@Resource
	private IExperimentService experimentService;
	@Resource
	private IPlanExperimentGroupService planExperimentGroupService;
	@Resource
	private IPlanService planService;

	@Override
	public List<TopicTargetPlanDateVo> getTargetPlanList(Long targetId) {
		List<TopicTargetPlanDateVo> targetPlanList = planTargetGroupMapper.getTargetPlanList(targetId);
		if (!CollectionUtils.isEmpty(targetPlanList)) {
			int i = 1;
			for (TopicTargetPlanDateVo target : targetPlanList) {
				if (BoolEnum.TRUE.getValue().equals(target.getIsHistory())) {
					target.setPlanDate("历史数据" + i);
					i++;
				} else {
					target.setPlanDate(target.getPlanTime() != null
							? DateUtil.dateString(target.getPlanTime(), DateUtil.DATE_HOUR_FORMAT) + "时"
							: "");
				}
			}
		}
		return targetPlanList;
	}

	@Override
	public PlanTargetGroup insert(PlanTargetGroup targetGroup) {
		int insert = planTargetGroupMapper.insert(targetGroup);
		Assert.isTrue(insert == 1, "添加失败");
		return targetGroup;
	}

	@Override
	@SuppressWarnings("unchecked")
	public PlanTargetGroup getNewestPlanTargetGroup(Long targetId) {
		LambdaQueryWrapper<PlanTargetGroup> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(PlanTargetGroup::getTopicTargetId, targetId);
		queryWrapper.eq(PlanTargetGroup::getIsDelete, BoolEnum.FALSE.getValue());
//		queryWrapper.eq(PlanTargetGroup::getState, TopicStateEnum.UNDER_WAY.getValue());
		queryWrapper.orderByAsc(PlanTargetGroup::getState);
		queryWrapper.orderByDesc(PlanTargetGroup::getPlanTime, PlanTargetGroup::getId);
		List<PlanTargetGroup> list = planTargetGroupMapper.selectList(queryWrapper);
		return CollectionUtils.isEmpty(list) ? null : list.get(0);
	}

	@Override
	public void updateById(PlanTargetGroup targetGroup) {
		planTargetGroupMapper.updateById(targetGroup);
	}

	@Override
	public PlanTargetGroup getById(Long targetGroupId) {
		return planTargetGroupMapper.selectById(targetGroupId);
	}

	@Override
	public void deleteById(Long targetGroupId) {
		planTargetGroupMapper.deleteById(targetGroupId);
	}

	@Override
	public void delete(Long topicId, Long topicDirectionId, Long topicTargetId) {
		if (topicId != null || topicDirectionId != null || topicTargetId != null) {
			LambdaQueryWrapper<PlanTargetGroup> wrapper = new LambdaQueryWrapper<PlanTargetGroup>();
			if (topicId != null)
				wrapper.eq(PlanTargetGroup::getTopicId, topicId);
			if (topicDirectionId != null)
				wrapper.eq(PlanTargetGroup::getTopicDirectionId, topicDirectionId);
			if (topicTargetId != null)
				wrapper.eq(PlanTargetGroup::getTopicTargetId, topicTargetId);
			planTargetGroupMapper.delete(wrapper);
		}
	}

	@Override
	public void endGroupByTopicId(Long topicId) {
		LambdaQueryWrapper<PlanTargetGroup> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(PlanTargetGroup::getTopicId, topicId);
		queryWrapper.eq(PlanTargetGroup::getIsDelete, BoolEnum.FALSE.getValue());
		queryWrapper.eq(PlanTargetGroup::getState, TopicStateEnum.UNDER_WAY.getValue());
		List<PlanTargetGroup> list = planTargetGroupMapper.selectList(queryWrapper);
		if(CollectionUtils.isNotEmpty(list)) {
			for (PlanTargetGroup planTargetGroup : list) {
				this.endTargetGroup(planTargetGroup.getId());
			}
		}
		experimentService.endExperimentByTopicId(topicId);
	}

	@Override
	public List<TopicTarget> selectListByTopicId(Long topicId) {
		return planTargetGroupMapper.selectListByTopicId(topicId);
	}

	@Override
	public void endTargetGroup(Long targetGroupId) {
		PlanTargetGroup targetGroup = new PlanTargetGroup();
		targetGroup.setId(targetGroupId);
		targetGroup.setState(TopicStateEnum.COMPLETE.getValue());
		this.updateById(targetGroup);

		List<TopicExperiment> topicExperimentList = planExperimentGroupService
				.getTopicExperimentList(targetGroup.getId(), null);
		if (CollectionUtils.isNotEmpty(topicExperimentList)) {
			List<Long> experimentIds = topicExperimentList.stream().map(TopicExperiment::getExperimentId)
					.collect(Collectors.toList());
			List<Experiment> experimentList = experimentService.selectByIdsAndNotEnd(experimentIds);
			if (CollectionUtils.isNotEmpty(experimentList)) {
				List<PlanExperimentGroup> experimentGroupList = planExperimentGroupService
						.getExperimentGroupList(targetGroupId);
				Map<Long, List<PlanExperimentGroup>> map = experimentGroupList.stream()
						.collect(Collectors.groupingBy(PlanExperimentGroup::getTopicExperimentId));
				Plan newestPlan = planService.getNewestPlan(targetGroupId);
				for (Experiment experiment : experimentList) {
					PlanExperimentGroup experimentGroup = map.get(experiment.getTopicExperimentId()).get(0);
					if (experiment.getStartTime()==null) {
						this.addAndEndPlan(targetGroupId, experimentGroup, newestPlan, experiment);
					}else {
						experimentService.endExperiment(experiment.getId(), null);
					}
				}
			}
		}
	}

	private void addAndEndPlan(Long targetGroupId, PlanExperimentGroup experimentGroup, Plan newestPlan,
			Experiment experiment) {
		Plan plan = new Plan();
		plan.setLabId(experiment.getLabId());
		plan.setTopicId(experiment.getTopicId());
		plan.setTopicDirectionId(experiment.getTopicDirectionId());
		plan.setTopicTargetId(experiment.getTopicTargetId());
		plan.setTopicExperimentId(experiment.getTopicExperimentId());
		plan.setExperimentId(experiment.getId());
		plan.setTargetGroupId(targetGroupId);
		
		plan.setExperimentGroupId(experimentGroup.getId());
		plan.setLabMemberId(experiment.getExecutorId());
		Date planTime = planService.getPlanTime(experiment.getExecutorId(),
				newestPlan != null ? newestPlan.getPlanTime() : new Date(), -1);
		plan.setPlanTime(planTime);
		plan = planService.insert(plan);

		experiment.setState(ExperimentStateEnum.COMPLETE.getValue());
		experiment.setStartTime(planTime);
		experiment.setEndTime(new Date());
		experimentService.updateById(experiment);
	}
}
